// Package request 提供HTTP响应处理功能，包含响应解析、结果获取等特性
package request

import (
	"fmt"
	"io"
	"net/http"
	"strconv"
	"strings"

	"gitee.com/tuboyou/c2/u2"
)

// Response 表示HTTP请求的响应结果
type Response struct {
	StatusCode      int                    `json:"status_code"`  // HTTP状态码
	Reason          string                 `json:"reason"`       // 状态描述
	Headers         map[string]string      `json:"headers"`      // 响应头
	ContentType     string                 `json:"content-type"` // 内容类型
	Result          string                 `json:"result"`       // 响应体内容
	Error           error                  `json:"error"`        // 错误信息
	StartTime       int64                  `json:"startTime"`    // 请求开始时间(毫秒)
	EndTime         int64                  `json:"endTime"`      // 请求结束时间(毫秒)
	Cost            int64                  `json:"cost"`         // 请求耗时(毫秒)
	Req             *Request               `json:"request"`      // 关联的请求对象
	Url             string                 `json:"url"`          // 请求URL
	resultInterface interface{}            // 解析后的响应体
	expectBody      map[string]interface{} // 期望的响应体结构
}

// newResponseByHttp 通过http.Response构建Response对象
//
// 参数：
//
//	code - 自定义状态码
//	resp - HTTP响应对象
//	startTime - 请求开始时间(毫秒)
//	req - 关联的请求对象
//	error - 错误信息
//
// 返回值：
//
//	Response - 构建的Response对象
//
// 注意：
//
//  1. 如果error不为nil，会直接返回包含错误信息的Response
//  2. 会自动解析响应体内容
func newResponseByHttp(code int, resp *http.Response, startTime int64, req *Request, error error) Response {
	res := &Response{
		EndTime:    u2.TimeNow().UnixMilli(),
		StartTime:  startTime,
		Req:        req,
		Error:      error,
		StatusCode: code,
		Headers:    make(map[string]string),
		expectBody: req.ExpectBody,
	}
	res.Cost = res.EndTime - res.StartTime

	if error != nil {
		return *res
	}

	res.StatusCode = resp.StatusCode
	res.Reason = strings.Replace(resp.Status, strconv.Itoa(resp.StatusCode)+" ", "", 1)
	res.Headers = make(map[string]string)

	// 处理响应头
	for k, v := range resp.Header {
		ss := strings.Join(v, "; ")
		if strings.ToLower(k) == "content-type" || strings.ToLower(k) == "contenttype" {
			res.ContentType = ss
		}
		res.Headers[k] = ss
	}

	// 读取响应体
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		res.Error = fmt.Errorf("读取响应体失败: %w", err)
		return *res
	}
	res.Result = string(body)
	resp.Body.Close()

	// 解析响应体
	u2.Json2Interface(body, &res.resultInterface)
	return *res
}

// GetResult 获取解析后的响应体
//
// 返回值：
//
//	interface{} - 解析后的响应体
//
// 注意：
//
//	返回的interface{}类型需要根据实际响应内容进行类型断言
func (r Response) GetResult() interface{} {
	return r.resultInterface
}

// GetExpectBody 获取期望的响应体结构
//
// 返回值：
//
//	map[string]interface{} - 期望的响应体结构
func (r Response) GetExpectBody() map[string]interface{} {
	return r.expectBody
}

// String 返回Response的字符串表示
//
// 返回值：
//
//	string - JSON格式的响应信息
//
// 注意：
//
//	如果序列化失败，会返回错误信息
func (r Response) String() string {
	if r.Error != nil {
		return r.Req.Url.String() + ",响应错误" + r.Error.Error()
	}
	if r.Req != nil && r.Req.Url != nil {
		r.Url = r.Req.Url.String()
	}
	da, err := u2.Struct2JSON(r, true)
	if err != nil {
		return r.Req.Url.String() + ",响应错误格式" + err.Error()
	}
	return da
}
